import {
	IController,
	ICtrlAbility,
	IDECtrlAbility,
	IParam,
	IViewLogicInput,
	getRouteParams,
	srfFilePath2,
	IViewEvent,
	IViewAbility,
	IViewStore,
	IMDViewAbility,
	IMDViewStore,
	IPickupViewStore,
	IPickupViewAbility,
	IMPickupViewStore,
	IMPickupViewAbility,
	IOptViewStore,
	IOptViewAbility,
	IExpViewModel,
	computedNavData,
	IExpViewStore,
	IExpViewAbility,
	deepCopy,
	IEvent,
} from '@/core';
import {
	IExpViewController,
	IMDViewController,
	IMPickupViewController,
	IOptViewController,
	IPickupViewController,
	IViewController,
} from '@/core/interface/view/controller';
import { IViewModel } from '@/core/interface/view/model/i-view-model';
import { router } from '@/router';
import {
	useAppStoreWithOut,
	useViewActionStoreWithOut,
	useViewCtxStoreWithOut,
} from '@/store';
import { formatRouteParams } from '@/utils';
import { createUUID, isNilOrEmpty, QXEvent } from 'qx-util';
import { useRoute } from 'vue-router';

/**
 * 计算导航参数
 *
 * @param {IViewController} controller
 * @param {IParam} props
 */
function computeNavParams(
	controller: IViewController<IViewStore, IViewAbility>,
	props: IParam
) {
	const model = controller.getModel<IParam>();
	const { context, viewParams } = useViewParams(model, props);
	const viewCtx = useViewCtx(context, viewParams, model, props);
	controller.setNavParams(context, viewParams, viewCtx);
}

/**
 * 计算视图参数
 *
 * @export
 * @param {IParam} model
 * @param {IParam} props
 * @return {*}  {{ context: IParam; viewParams: IParam }}
 */
export function useViewParams(
	model: IParam,
	props: IParam
): { context: IParam; viewParams: IParam } {
	const { getAppData: appData } = useAppStoreWithOut();

	const { context: propContext, viewParams: propViewParams, openType } = props;
	// 应用上下文
	const context: IParam = {};
	// 视图参数
	const viewParams: IParam = {};
	// 非路由模式视图（包含模态，嵌入）
	if (openType !== 'ROUTE') {
		Object.assign(context, propContext);
		Object.assign(viewParams, propViewParams);
		if (
			isNilOrEmpty(context.srfsessionid) &&
			isNilOrEmpty(context.srfsessionkey)
		) {
			context.srfsessionid = createUUID();
		}
		if (context && context.srfparentdename) {
			Object.assign(viewParams, { srfparentdename: context.srfparentdename });
		}
		if (context && context.srfparentkey) {
			Object.assign(viewParams, { srfparentkey: context.srfparentkey });
		}
	} else {
		Object.assign(context, appData && appData.context ? appData.context : {});
		const { fullPath, params } = useRoute();
		// 应用级参数
		const appRouteParams = getRouteParams(window.location.href);
		Object.assign(context, appRouteParams);
		formatRouteParams(params, fullPath, context, viewParams);
		// 定义顶层视图srfsessionid
		context.srfsessionid = createUUID();
	}
	// 计算自定义参数
	const appViewConfig = App.getAppViewConfig();
	const view = appViewConfig[model.codeName];
	if (
		view &&
		view.navigateContext &&
		Object.keys(view.navigateContext).length > 0
	) {
		const localContext = computedNavData(
			{},
			context,
			viewParams,
			view.navigateContext
		);
		Object.assign(context, localContext);
	}
	if (
		view &&
		view.navigateParams &&
		Object.keys(view.navigateParams).length > 0
	) {
		const localViewParam = computedNavData(
			{},
			context,
			viewParams,
			view.navigateParams
		);
		Object.assign(viewParams, localViewParam);
	}
	return { context, viewParams };
}

/**
 * 计算视图操作参数
 *
 * @export
 * @param {IParam} context
 * @param {IParam} viewParam
 */
export function useViewCtx(
	context: IParam,
	viewParam: IParam,
	model: IParam,
	props: IParam
) {
	const viewCtx: IParam = {};
	const { openType } = props;
	// 应用全局数据对象
	const { getAppGlobal, getRouteViewGlobal, setRouteViewGlobal } =
		useViewCtxStoreWithOut();
	viewCtx['appGlobal'] = getAppGlobal();
	if (openType === 'ROUTE') {
		setRouteViewGlobal(context.srfsessionid, {});
	}
	// 路由视图全局数据对象（嵌入视图可共享）
	viewCtx['routeViewGlobal'] = getRouteViewGlobal();
	return viewCtx;
}

/**
 * 导航参数绑定
 *
 * @export
 * @param {IViewController} controller
 * @param {IParam} props
 */
export function useNavParamsBind(
	controller: IViewController<IViewStore, IViewAbility>,
	props: IParam
) {
	watch(
		() => props.context,
		() => {
			computeNavParams(controller, props);
		},
		{ immediate: true }
	);
	watch(
		() => props.viewParams,
		() => {
			computeNavParams(controller, props);
		},
		{ immediate: true }
	);
}

/**
 * 视图事件绑定
 *
 * @export
 * @template T
 * @template A
 * @param {Function} emit
 * @return {*}  {QXEvent<IViewEvent<T, A>>}
 */
export function useEventBind<T, A extends IViewAbility>(
	emit: Function
): QXEvent<IViewEvent<T, A>> {
	const evt = new QXEvent<IViewEvent<T, A>>();
	//  绑定事件回调
	evt.on('viewAction', (controlName: string, action: T, data: any) => {
		emit('view-action', controlName, action, data);
	});
	evt.on('viewInit', (controlName: string, data: A) => {
		emit('view-init', controlName, data);
	});
	evt.on('viewMounted', (controlName: string, data: IParam) => {
		emit('view-mounted', controlName, data);
	});
	evt.on('viewDestroy', (controlName: string, data: IParam) => {
		emit('view-destroy', controlName, data);
	});
	return evt;
}

/**
 * 工具栏点击
 *
 * @export
 * @param {IViewController} controller
 * @param {string} name
 * @param {MouseEvent} event
 * @param {IParam} [logic]
 * @return {*}
 */
export function handleToolbarItemClick(
	controller: IController,
	name: string,
	event: MouseEvent,
	logic?: IViewLogicInput
) {
	if (!logic) {
		console.warn('无事件逻辑');
		return;
	}
	const model = controller.getModel<IViewModel>();
	if (!logic.xDataCtrlName) {
		console.warn('无数据目标部件');
	} else {
		// 触发源为部件
		if (model?.name?.toLowerCase() === logic.xDataCtrlName.toLowerCase()) {
			// TOTO
		}
		// 触发源为视图
		else {
			// 获取参数
			const { context, viewParams } = controller.getStore();
			const tempContext = deepCopy(context);
			const tempViewParams = deepCopy(viewParams);
			// 获取能力
			let ability: any = controller.getSubAbility<ICtrlAbility>(
				logic.xDataCtrlName.toLowerCase()
			) as IDECtrlAbility;
			const ctrl = ability.controller;
			// 获取数据
			const data: IParam[] = ability.getData();
			//  特殊识别，导出时合并导出参数
			if (logic.actionTag === 'ExportExcel') {
				Object.assign(viewParams, {
					srfactionparams: {
						type: (logic as IParam).type,
						startPage: (logic as IParam).startPage,
						endPage: (logic as IParam).endPage,
					},
				});
			}
			//  特殊识别，当行为标识为ToggleFilter时，使用视图能力
			if (logic.actionTag === 'ToggleFilter') {
				ability = controller.getAbility();
			}
			Object.assign(ability.viewCtx, { ctrl });
			// 执行视图逻辑
			App.getViewLogicHelper().executeViewLogic(
				tempContext,
				tempViewParams,
				data,
				event,
				ability,
				logic
			);
		}
	}
}

/**
 * 处理部件初始化
 *
 * @export
 * @template C
 * @param {C} controller 控制器
 * @param {string} name 部件名称
 * @param {ICtrlAbility} ability 部件能力
 */
export function handleCtrlInit<
	C extends IViewController<IViewStore, IViewAbility>,
	A extends ICtrlAbility
>(controller: C, name: string, ability: A) {
	controller.handleCtrlInit(name, ability);
}

/**
 * 处理部件行为
 *
 * @export
 * @template C
 * @template A
 * @param {C} controller 控制器
 * @param {string} name 部件名称
 * @param {A} action 行为标识
 * @param {IParam[]} data 数据
 */
export function handleCtrlAction<
	C extends IViewController<IViewStore, IViewAbility>,
	A extends string
>(controller: C, name: string, action: A, data: IParam[]) {
	controller.handleCtrlAction(name, action, data);
}

/**
 * 处理部件销毁
 *
 * @export
 * @template C
 * @param {C} controller 控制器
 * @param {string} name 部件名称
 * @param {IParam} data 数据
 */
export function handleCtrlDestroy<
	C extends IViewController<IViewStore, IViewAbility>
>(controller: C, name: string, data: IParam) {
	controller.handleCtrlDestroy(name, data);
}

/**
 * 处理选项操作视图按钮行为
 *
 * @export
 * @template C
 * @template A
 * @param {C} controller
 * @param {('confirm' | 'cancel')} type
 */
export function handleOptViewButtonAction<
	C extends IOptViewController<IOptViewStore, IOptViewAbility>,
	A extends string
>(controller: C, type: 'confirm' | 'cancel') {
	if (type === 'cancel') {
		controller.cancel();
	}
	if (type === 'confirm') {
		controller.confirm();
	}
}

/**
 * 处理多项选择视图选择按钮行为
 *
 * @export
 * @template C
 * @param {C} controller
 * @param {('toLeft' | 'toRight' | 'toAllLeft' | 'toAllRight')} type
 */
export function handleMPickupViewPickButtonAction<
	C extends IMPickupViewController<IMPickupViewStore, IMPickupViewAbility>
>(controller: C, type: 'toLeft' | 'toRight' | 'toAllLeft' | 'toAllRight') {
	controller.handleMPickupViewPickButtonAction(type);
}

/**
 * 处理选择视图按钮行为
 *
 * @export
 * @template C
 * @param {C} controller
 * @param {('confirm' | 'cancel')} type
 */
export function handlePickupViewButtonAction<
	C extends IPickupViewController<IPickupViewStore, IPickupViewAbility>
>(controller: C, type: 'confirm' | 'cancel') {
	if (type === 'confirm') {
		controller.confirm();
	}
	if (type === 'cancel') {
		controller.cancel();
	}
}

/**
 * 处理多项选择视图行为
 *
 * @export
 * @template C
 * @param {C} controller
 * @param {string} action
 * @param {IParam} data
 */
export function handleMPickupViewAction<
	C extends IMPickupViewController<IMPickupViewStore, IMPickupViewAbility>
>(controller: C, action: string, data: IParam) {
	controller.handleMPickupViewAction(action, data);
}

/**
 * 处理多数据视图快速分组值变化
 *
 * @export
 * @param {IMDViewController} controller
 * @param {IParam} item
 */
export function handleQuickGroupValueChange(
	controller:
		| IMDViewController<IMDViewStore, IMDViewAbility>
		| IExpViewController<IExpViewStore, IExpViewAbility>,
	item: IParam
) {
	controller.handleQuickGroupValueChange(item);
}

/**
 * 处理组件行为
 *
 * @export
 * @param {IViewController<IViewStore, IViewAbility>} controller
 * @param {IEvent<string>} actionParam
 * @param {number} [index]
 */
export function handleComponentAction(
	controller: IViewController<IViewStore, IViewAbility>,
	actionParam: IEvent<string>,
	index?: number
) {
	controller.handleComponentAction(actionParam, index);
}

/**
 * 视图类名
 *
 * @export
 * @param {*} [model={}] 视图模型
 * @param {string} [customClassNames] 自定义样式名
 * @return {*}  {string}
 */
export function getViewClassNames(
	model: IParam = {},
	props: IParam = {}
): IParam {
	const classNames: IParam = {};
	if (model.viewStyle) {
		Object.assign(classNames, {
			[`view-style-${model.viewStyle.toLowerCase()}`]: true,
		});
	}
	if (model.viewType) {
		Object.assign(classNames, { [model.viewType.toLowerCase()]: true });
	}
	if (model.codeName) {
		Object.assign(classNames, { [srfFilePath2(model.codeName)]: true });
	}
	if (model.cssName) {
		Object.assign(classNames, { [model.cssName]: true });
	}
	if (!model.useDefaultLayout) {
		Object.assign(classNames, {
			'view-layout': true,
			[`view-layout--${model.layoutMode.toLowerCase()}`]: true,
		});
	}
	return classNames;
}

/**
 * 编辑视图类名
 *
 * @export
 * @param {IParam} [model={}] 视图模型
 * @param {IParam} [props={}] 视图输入参数
 * @param {IParam} [customClassNames={}] 自定义类名
 * @return {*}
 */
export function getEditViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 多表单编辑视图类名
 *
 * @export
 * @param {IParam} [model={}]
 * @param {IParam} [props={}]
 * @param {IParam} [customClassNames]
 * @return {*}
 */
export function getMEditViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 首页视图类名
 *
 * @export
 * @param {IParam} [model={}] 视图模型
 * @param {IParam} [props={}] 视图输入参数
 * @param {IParam} [customClassNames={}] 自定义类名
 * @return {*}
 */
export function getIndexViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames: IParam = {
		'app-container': true,
	};
	if (model.viewStyle) {
		Object.assign(classNames, {
			[`app-style-${model.viewStyle.toLowerCase()}`]: true,
		});
	}
	if (model.viewType) {
		Object.assign(classNames, { [model.viewType.toLowerCase()]: true });
	}
	if (model.codeName) {
		Object.assign(classNames, { [srfFilePath2(model.codeName)]: true });
	}
	if (model.cssName) {
		Object.assign(classNames, { [model.cssName]: true });
	}
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	Object.assign(classNames, {
		[`app-content--${model.viewStyle === 'DEFAULT' ? 'tab' : 'route'}`]: true,
	});
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 选项操作视图类名
 *
 * @export
 * @param {IParam} [model={}] 视图模型
 * @param {IParam} [props={}] 视图输入参数
 * @param {IParam} [customClassNames={}] 自定义类名
 * @return {*}
 */
export function getOptViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 门户视图类名
 *
 * @export
 * @param {IParam} [model={}] 视图模型
 * @param {IParam} [props={}] 视图输入参数
 * @param {IParam} [customClassNames={}] 自定义类名
 * @return {*}
 */
export function getPortalViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 树视图类名
 *
 * @export
 * @param {IParam} [model={}] 视图模型
 * @param {IParam} [props={}] 视图输入参数
 * @param {IParam} [customClassNames={}] 自定义类名
 * @return {*}
 */
export function getTreeViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 树导航视图类名
 *
 * @export
 * @param {IParam} [model={}]
 * @param {IParam} [props={}]
 * @param {IParam} [customClassNames]
 * @return {*}
 */
export function getTreeExpBarViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * HTML视图类名
 *
 * @export
 * @param {IParam} [model={}]
 * @param {IParam} [props={}]
 * @param {IParam} [customClassNames]
 * @return {*}
 */
export function getHtmlViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 自定义视图类名
 *
 * @export
 * @param {IParam} [model={}]
 * @param {IParam} [props={}]
 * @param {IParam} [customClassNames]
 * @return {*}
 */
export function getCustomViewClassNames(
	model: IParam = {},
	props: IParam = {},
	customClassNames?: IParam
) {
	const classNames = getViewClassNames(model, props);
	if (customClassNames) {
		Object.assign(classNames, customClassNames);
	}
	return classNames;
}

/**
 * 获取导航视图类名
 *
 * @export
 * @param {IExpViewModel} model
 * @param {IParam} [props={}]
 * @param {IParam} [customClassNames={}]
 * @return {*}
 */
export function getExpViewClassNames(
	model: IExpViewModel,
	props: IParam = {},
	customClassNames: IParam = {}
) {
	const classNames = getViewClassNames(model, props);
	Object.assign(classNames, { deexpview: true });
	Object.assign(classNames, customClassNames);
	return classNames;
}

/**
 * 初始化导航视图分隔值
 *
 * @export
 * @param {HTMLElement} element
 * @param {IExpViewModel} model
 * @return {*}  {(number | undefined)}
 */
export function initExpViewSplit(
	element: HTMLElement,
	model: IExpViewModel
): number | undefined {
	const { expBarWidth, expBarName, expBarHeight, sideBarLayout } = model;
	if (!element || !expBarName) {
		return undefined;
	}
	const tempSplit = getExpViewSplit(model);
	if (tempSplit) {
		return tempSplit;
	}
	if (sideBarLayout === 'LEFT' && expBarWidth && expBarWidth > 0) {
		const split = expBarWidth / element.offsetWidth;
		setExpViewSplit(model, split);
		return split;
	}
	if (sideBarLayout === 'TOP' && expBarHeight && expBarHeight > 0) {
		const split = expBarHeight / element.offsetHeight;
		setExpViewSplit(model, split);
		return split;
	}
	return undefined;
}

/**
 * 获取导航视图分隔值
 *
 * @export
 * @param {IExpViewModel} model
 * @return {*}  {(number | undefined)}
 */
export function getExpViewSplit(model: IExpViewModel): number | undefined {
	const { codeName, expBarName } = model;
	const { getViewSplit } = useViewActionStoreWithOut();
	return getViewSplit(`${codeName}_${expBarName}`);
}

/**
 *设置导航视图分隔值
 *
 * @export
 * @param {IExpViewModel} model
 * @param {number} split
 */
export function setExpViewSplit(model: IExpViewModel, split: number) {
	const { setViewSplit } = useViewActionStoreWithOut();
	const { codeName, expBarName } = model;
	setViewSplit(`${codeName}_${expBarName}`, split);
}

/**
 * 处理快速搜索
 *
 * @export
 * @param {IMDViewController<IMDViewStore, IMDViewAbility>} controller
 * @param {string} searchValue
 */
export function handleQuickSearch(
	controller: IMDViewController<IMDViewStore, IMDViewAbility>,
	searchValue: string
) {
	controller.search(searchValue);
}
